#include <mpi.h>
#include <stdio.h>
#include <string.h>

#include "broadcast.h"
#include "../utils/utils.h"

#include <omp.h>

int broadcast(struct algorithm_data* info)
{
	struct matrix_t* buf;
	long bufsize;
	int bcpid;
	int err=0;
	double t1, t2, tcomm=0, tcpu=0;

	err |= alloc_matrix_b(&buf, info->b->n, info->b->m);
	bufsize = info->b->m * info->b->n;

	for (bcpid = 0; bcpid < info->info->num_procs; ++bcpid) {
		if (bcpid != info->info->proc_id) {
			t1 = MPI_Wtime();
			err |= MPI_Bcast(
				buf->mat, 
				bufsize, 
				MPI_LONG, 
				bcpid,
				MPI_COMM_WORLD);
			tcomm += MPI_Wtime() - t1;

			t2 = MPI_Wtime();
			err |= calc(info, buf, bcpid);
			tcpu += MPI_Wtime() - t2;

		} else {
			t1 = MPI_Wtime();
			err |= MPI_Bcast(
				info->b->mat,
				bufsize,
				MPI_LONG,
				bcpid,
				MPI_COMM_WORLD);
			tcomm += MPI_Wtime() - t1;

			t2 = MPI_Wtime();
			err |= diag_calc(info);
			tcpu += MPI_Wtime() - t2;
		}
	}

	printf("bc.%d [tcomm=%f, tcpu=%f]\n", info->info->proc_id, tcomm, tcpu);
	return err;
}


int no_comm(struct algorithm_data* info)
{
	struct matrix_t* buf;
	long bufsize;
	int bcpid;
	int err=0, i;
	double t1, t2, tcomm=0, tcpu=0;

	err |= alloc_matrix_b(&buf, info->b->n, info->b->m);
	bufsize = info->b->m * info->b->n;

	for (bcpid = 0; bcpid < info->info->num_procs; ++bcpid) {
		if (bcpid != info->info->proc_id) {
			memset(info->b->mat, bcpid, info->b->m*info->b->n);

			t2 = MPI_Wtime();
			err |= calc(info, info->b, bcpid);
			tcpu += MPI_Wtime() - t2;
		} else {
			t2 = MPI_Wtime();
			err |= diag_calc(info);
			tcpu += MPI_Wtime() - t2;
		}
	}

	printf("nc.%d [tcomm=%f, tcpu=%f]\n", info->info->proc_id, tcomm, tcpu);
	return err;
}

